home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_oth / libry31a / libry3.doc < prev    next >
Text File  |  1987-01-20  |  16KB  |  372 lines

  1. .pa
  2.                      STRING AND BUFFER MANIPULATION
  3.  
  4. The  purpose of these procedures is that FORTRAN is rather ill suited to
  5. string and buffer manipulation.  Most of the operations can be  done  in
  6. FORTRAN  but  are  extremely  slow  in  comparison.   Also  there is the
  7. annoying practice of some compilers (e.g.   HP's  FTN7X)  to  use  fixed
  8. length  character  variables.   All  of  these  routines were written in
  9. assembler.
  10. .pa
  11.               QUICK LIST OF STRING AND BUFFER MANIPULATION
  12.  
  13. CSET:   set all the characters in a string
  14. FOLD:   case fold a character (a-z folds to A-Z)
  15. FOLDS:  case fold a character string (a-z folds to A-Z)
  16. ISERCH: search for a character in a string
  17. MATCH:  check two character strings for a match
  18. MOVEC:  move one character string into another
  19. MOVEI:  move one integer array into another
  20. NBUFC1: determine the nominal length of a character string
  21. SWAPC:  swap two character strings
  22. SWAPI:  swap two integer arrays
  23. SORTC:  sort a group of character strings
  24. SORTCI: sort a group of indexed character strings
  25. SORTD:  sort an array of double precision reals
  26. SORTDI: sort an array of indexed double precision reals
  27. SORTI:  sort an array of integers
  28. SORTII: sort an array of indexed integers
  29. SORTR:  sort an array of reals
  30. SORTRI: sort an array of indexed reals
  31. DEC0DE: decode an array of reals contained in a character string
  32. .pa
  33. NAME:     CSET
  34. PURPOSE:  set all the characters in a string equal to a specific
  35.           character (such as blanks)
  36. TYPE:     subroutine (far external)
  37. SYNTAX:   CALL CSET(CBUF,' ',NBUF)
  38. INPUT:    a CHARACTER*1 variable (here ' ')
  39.           NBUF (INTEGER*2) number of characters in the target string
  40. OUTPUT:   CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
  41.  
  42.  
  43. NAME:     FOLD
  44. PURPOSE:  case fold a character (a-z folds to A-Z)
  45. TYPE:     CHARACTER*1 function (far external)
  46. SYNTAX:   C2=FOLD(C1)
  47. INPUT:    C1 (CHARACTER*1)
  48. OUTPUT:   C2 (CHARACTER*1)
  49.  
  50.  
  51. NAME:     FOLDS
  52. PURPOSE:  case fold a character string (a-z folds to A-Z)
  53. TYPE:     subroutine (far external)
  54. SYNTAX:   CALL FOLDS(CBUF,NBUF)
  55. INPUT:    CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
  56.           NBUF (INTEGER*2) number of characters in the string
  57. OUTPUT:   CBUF
  58.  
  59.  
  60. NAME:     ISERCH
  61. PURPOSE:  search for a character in a string
  62. TYPE:     INTEGER*2 function (far external)
  63. SYNTAX:   K=ISERCH('?','are you kidding?',NBUF)
  64. INPUT:    a CHARACTER*1 variable (here '?')
  65.           CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
  66.           NBUF (INTEGER*2) number of characters in the string
  67. OUTPUT:   K (INTEGER*2)
  68. NOTE:     0<=K<=NBUF (if found, I will be first occurrence, if not
  69.           found, K=0)
  70.  
  71.  
  72. NAME:     MATCH
  73. PURPOSE:  check two character strings for a match
  74. TYPE:     LOGICAL*2 function (far external)
  75. SYNTAX:   IF(MATCH(CBUF,'STOP',4)) GO TO 999
  76. INPUT:    two character strings (may be CHARACTER*1 CBUF1(NBUF),
  77.           CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
  78.           NBUF (INTEGER*2) number of characters in the strings
  79. OUTPUT:   .true./.false.
  80. NOTE:     the strings need not have the same length as long as they are
  81.           both at least NBUF in length (here NBUF=4)
  82.  
  83.           One annoying thing about FORTRAN is that it won't compare the
  84.           first 4 characters of a string read in as 4A1 with a string
  85.           of length 4 like 'STOP'. MATCH solves this problem.
  86.  
  87.  
  88. NAME:     MOVEC
  89. PURPOSE:  move one character string into another
  90. TYPE:     subroutine (far external)
  91. SYNTAX:   CALL MOVEC(CBUF1,CBUF2,NBUF) or CALL MOVEC(CBUF,'STOP',4)
  92. INPUT:    CBUF2 a character string (may be CHARACTER*1 CBUF2(NBUF) or
  93.           CHARACTER*4 CBUF2)
  94.           NBUF (INTEGER*2) number of characters in the strings
  95. OUTPUT:   CBUF1 a character string (may be CHARACTER*1 CBUF1(NBUF) or
  96.           CHARACTER*4 CBUF1)
  97. NOTE:     the strings need not have the same length as long as they are
  98.           both at least NBUF in length (here NBUF=4)
  99.  
  100.           One annoying thing about FORTRAN is that it won't equivalence
  101.           first 4 characters of a 4A1 string to a string of length 4
  102.           like 'STOP'. MOVEC solves this problem. It's also much faster.
  103.  
  104.  
  105. NAME:     MOVEI
  106. PURPOSE:  move one integer array into another
  107. TYPE:     subroutine (far external)
  108. SYNTAX:   CALL MOVEI(IBUF1,IBUF2,NBUF)
  109. INPUT:    IBUF2 (INTEGER*2) an array
  110.           NBUF (INTEGER*2) number of elements in the arrays
  111. OUTPUT:   IBUF1 (INTEGER*2) an array
  112. NOTE:     the strings need not have the same length as long as they are
  113.           both at least NBUF in length
  114.  
  115.           This is about seventeen times as fast as a FORTRAN "DO LOOP".
  116.  
  117.  
  118. NAME:     NBUFC1
  119. PURPOSE:  determine the nominal length of a character string excluding
  120.           trailing blanks
  121. TYPE:     INTEGER*2 function (far external)
  122. SYNTAX:   IF(NBUFC1(CBUF,80).EQ.0) STOP   or
  123.           L=NBUFC1(CBUF,NBUF)
  124. INPUT:    CBUF a character string (may be CHARACTER*1 CBUF(NBUF) or
  125.           CHARACTER*4 CBUF)
  126.           NBUF (INTEGER*2) total number of characters in the string
  127. OUTPUT:   L (INTEGER*2) nominal length of string
  128.  
  129.  
  130. NAME:     SWAPC
  131. PURPOSE:  swap two character strings
  132. TYPE:     subroutine (far external)
  133. SYNTAX:   CALL SWAPC(CBUF1,CBUF2,NBUF)
  134. INPUT:    CBUF1 and CBUF2 character strings (may be CHARACTER*1
  135.           CBUF1(NBUF),CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
  136.           NBUF (INTEGER*2) number of characters in the strings
  137. OUTPUT:   CBUF1,CBUF2
  138. NOTE:     the strings need not have the same length as long as they are
  139.           both at least NBUF in length
  140.  
  141.  
  142. NAME:     SWAPI
  143. PURPOSE:  swap two integer arrays
  144. TYPE:     subroutine (far external)
  145. SYNTAX:   CALL SWAPI(IBUF1,IBUF2,NBUF)
  146. INPUT:    IBUF1,IBUF2 (INTEGER*2) an arrays
  147.           NBUF (INTEGER*2) number of elements in the arrays
  148. OUTPUT:   IBUF1,IBUF2
  149. NOTE:     the arrays need not have the same length as long as they are
  150.           both at least NBUF in length
  151.  
  152.  
  153. NAME:     SORTC
  154. PURPOSE:  sort a group of character strings
  155. TYPE:     subroutine (far external)
  156. SYNTAX:   CALL SORTC(GROUP,L,N,ASCEND)
  157. INPUT:    GROUP a group of character strings (may be CHARACTER*1
  158.           GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
  159.           L (INTEGER*2) length of the strings
  160.           N (INTEGER*2) number of strings in group
  161.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  162.           descending order
  163. OUTPUT:   GROUP
  164. NOTE:     A modification of the shell sort is used.
  165.  
  166.           This operation isn't even possible in FORTRAN because you
  167.           can't pass the length of a character variable as a formal
  168.           parameter.
  169.  
  170. WARNING:  Be careful that GROUP does not cross a segment boundary!
  171.           That is, GROUP can not contain more than 65356 bytes nor
  172.           be part of a data group that spans a segment boundary. See
  173.           the comments in the section on vector emulation for more
  174.           details on segment boundaries.
  175.  
  176.  
  177. NAME:     SORTCI
  178. PURPOSE:  sort a group of indexed character strings
  179. TYPE:     subroutine (far external)
  180. SYNTAX:   CALL SORTCI(GROUP,L,INDEX,N,ASCEND)
  181. INPUT:    GROUP a group of character strings (may be CHARACTER*1
  182.           GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
  183.           L (INTEGER*2) length of the strings
  184.           INDEX (INTEGER*2) some index like 1,2,3,4,5...
  185.           N (INTEGER*2) number of strings in group
  186.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  187.           descending order
  188. OUTPUT:   GROUP, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
  189.           upon return from SORTCI you can tell what the change was from
  190.           the original order - INDEX will come back as something like
  191.           13,2,35,27,3,18,...)
  192. NOTE:     A modification of the shell sort is used.
  193.  
  194.           This operation isn't even possible in FORTRAN because you
  195.           can't pass the length of a character variable as a formal
  196.           parameter.
  197.  
  198. WARNING:  Be careful that GROUP and INDEX do not cross segment
  199.           boundaries. That is, GROUP can not contain more than 65356
  200.           bytes and INDEX can not contain mode than 32768 elements nor
  201.           be part of a data group that spans a segment boundary. See
  202.           the comments in the section on vector emulation for more
  203.           details on segment boundaries.
  204.  
  205.  
  206. NAME:     SORTD
  207. PURPOSE:  sort an array of double precision reals
  208. TYPE:     subroutine (far external)
  209. SYNTAX:   CALL SORTD(D,N,ASCEND)
  210. INPUT:    D (REAL*8) array
  211.           N (INTEGER*2) number of elements in D
  212.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  213.           descending order
  214. OUTPUT:   D
  215. NOTE:     A modification of the shell sort is used.
  216.  
  217. WARNING:  Be careful that D does not cross a segment boundary!
  218.           That is, D can not contain more than 8192 elements nor
  219.           be part of a data group that spans a segment boundary. See
  220.           the comments in the section on vector emulation for more
  221.           details on segment boundaries.
  222.  
  223.  
  224. NAME:     SORTDI
  225. PURPOSE:  sort an array of indexed double precision reals
  226. TYPE:     subroutine (far external)
  227. SYNTAX:   CALL SORTDI(D,INDEX,N,ASCEND)
  228. INPUT:    D (REAL*8) array
  229.           INDEX (INTEGER*2) some index like 1,2,3,4,5...
  230.           N (INTEGER*2) number of elements in D
  231.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  232.           descending order
  233. OUTPUT:   D, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
  234.           upon return from SORTDI you can tell what the change was from
  235.           the original order - INDEX will come back as something like
  236.           13,2,35,27,3,18,...)
  237. NOTE:     A modification of the shell sort is used.
  238.  
  239. WARNING:  Be careful that D and INDEX do not cross segment
  240.           boundaries. That is, D can not contain more than 8192
  241.           bytes and INDEX can not contain mode than 32766 elements nor
  242.           be part of a data group that spans a segment boundary. See
  243.           the comments in the section on vector emulation for more
  244.           details on segment boundaries.
  245.  
  246.  
  247. NAME:     SORTI
  248. PURPOSE:  sort an array of integers
  249. TYPE:     subroutine (far external)
  250. SYNTAX:   CALL SORTI(K,N,ASCEND)
  251. INPUT:    K (INTEGER*2) array
  252.           N (INTEGER*2) number of elements in K
  253.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  254.           descending order
  255. OUTPUT:   K
  256. NOTE:     A modification of the shell sort is used.
  257.  
  258. WARNING:  Be careful that K does not cross a segment boundary!
  259.           That is, K can not contain more than 32768 elements nor
  260.           be part of a data group that spans a segment boundary. See
  261.           the comments in the section on vector emulation for more
  262.           details on segment boundaries.
  263.  
  264.  
  265. NAME:     SORTII
  266. PURPOSE:  sort an array of indexed integers
  267. TYPE:     subroutine (far external)
  268. SYNTAX:   CALL SORTII(K,INDEX,N,ASCEND)
  269. INPUT:    K (INTEGER*2) array
  270.           INDEX (INTEGER*2) some index like 1,2,3,4,5...
  271.           N (INTEGER*2) number of elements in K
  272.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  273.           descending order
  274. OUTPUT:   K, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
  275.           upon return from SORTII you can tell what the change was from
  276.           the original order - INDEX will come back as something like
  277.           13,2,35,27,3,18,...)
  278. NOTE:     A modification of the shell sort is used.
  279.  
  280. WARNING:  Be careful that K and INDEX do not cross segment
  281.           boundaries. That is, K can not contain more than 32768
  282.           bytes and INDEX can not contain mode than 32766 elements nor
  283.           be part of a data group that spans a segment boundary. See
  284.           the comments in the section on vector emulation for more
  285.           details on segment boundaries.
  286.  
  287.  
  288. NAME:     SORTR
  289. PURPOSE:  sort an array of reals
  290. TYPE:     subroutine (far external)
  291. SYNTAX:   CALL SORTR(R,N,ASCEND)
  292. INPUT:    R (REAL*4) array
  293.           N (INTEGER*2) number of elements in R
  294.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  295.           descending order
  296. OUTPUT:   R
  297. NOTE:     A modification of the shell sort is used.
  298.  
  299. WARNING:  Be careful that R does not cross a segment boundary!
  300.           That is, R can not contain more than 16384 elements nor
  301.           be part of a data group that spans a segment boundary. See
  302.           the comments in the section on vector emulation for more
  303.           details on segment boundaries.
  304.  
  305.  
  306. NAME:     SORTRI
  307. PURPOSE:  sort an array of indexed reals
  308. TYPE:     subroutine (far external)
  309. SYNTAX:   CALL SORTRI(R,INDEX,N,ASCEND)
  310. INPUT:    R (REAL*4) array
  311.           INDEX (INTEGER*2) some index like 1,2,3,4,5...
  312.           N (INTEGER*2) number of elements in R
  313.           ASCEND (LOGICAL*2) .true. for ascending order, .false. for
  314.           descending order
  315. OUTPUT:   R, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
  316.           upon return from SORTRI you can tell what the change was from
  317.           the original order - INDEX will come back as something like
  318.           13,2,35,27,3,18,...)
  319. NOTE:     A modification of the shell sort is used.
  320.  
  321. WARNING:  Be careful that R and INDEX do not cross segment
  322.           boundaries. That is, R can not contain more than 16384
  323.           bytes and INDEX can not contain mode than 32766 elements nor
  324.           be part of a data group that spans a segment boundary. See
  325.           the comments in the section on vector emulation for more
  326.           details on segment boundaries.
  327.  
  328.  
  329. NAME:     DEC0DE (note the "0" (zero), do not use an "O" (oh))
  330. PURPOSE:  decode an array of reals contained in a character string
  331. TYPE:     subroutine (far external)
  332. SYNTAX:   CALL DEC0DE(CBUF,NBUF,NCOL,R,N,IER)
  333. INPUT:    CBUF (any character string like '123 34.E4 5*0 100')
  334.           NBUF (INTEGER*2) the number of characters in CBUF
  335.           N (INTEGER*2) number of elements in R
  336. OUTPUT:   NCOL (INTEGER*2) the column where decoding stopped
  337.           R (REAL*4) an array (may be only 1 element)
  338.           IER (INTEGER*2) error return indicator (IER=0 is normal)
  339. NOTE:     In case you haven't noticed, some misguided persons at DEC and
  340.           Microsoft forgot to include the capability of free-format
  341.           reads from a character string (some people call character
  342.           strings "internal files" - why, is a mystery to me). Of
  343.           course, this is the most OBVIOUS reason for reading something
  344.           from a character string... perhaps that's why they left it
  345.           out. Well, DEC0DE is just the fix.
  346.  
  347.           DEC0DE will return an error if the syntax is incorrect or if
  348.           the string is empty. You must have at least one number in the
  349.           string. Missing numbers at the trailing end of a string will
  350.           be set to zero (viz. if you try to read 6 numbers and there
  351.           are only 3, the last 3 will come back as zero).
  352.  
  353.           Some examples of free format reals are given below. Note that
  354.           you can use the "*" to repeat numbers. Commas are optional.
  355.  
  356.                100 1.234 .0000123,45E4, 3*53.123 5*-7 -12.345E-05
  357.  
  358.           DEC0DE is written in assembler and is actually faster than
  359.           Microsoft's or HP's equivalent.  HP's FORTRAN will actually
  360.           perform this operation.
  361.  
  362.           When I want to read integers from a character string I first
  363.           read reals, then apply the "NINT" function as below
  364.  
  365.                CALL DEC0DE(CBUF,6,NCOL,R,1,IER)
  366.                IF(IER.NE.0) GO TO 999
  367.                I=NINT(R)
  368.  
  369.           The NINT function performs the real>integer conversion that is
  370.           what you probably want: (nearest integer) rather than the INT
  371.           function (truncate to integer).
  372.